package com.utry.license.server.license;

import com.utry.license.common.LicenseManagerHolder;
import com.utry.license.common.UtryLicenseManager;
import com.utry.license.common.base.ErrorEnum;
import com.utry.license.common.base.ErrorUtil;
import com.utry.license.server.dto.LicenseCreateDTO;
import de.schlichtherle.license.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.security.auth.x500.X500Principal;
import java.util.Date;
import java.util.Objects;
import java.util.prefs.Preferences;

/**
 *
 * @description 证书生成器
 *
 * @author renxin
 *
 * @email renxinzhiliangzhi@163.com
 * 
 * @date 2019/7/25 13:16
 */
@Slf4j
@Component
public class LicenseCreator {

    @Autowired
    private LicenseConfigBean licenseConfigBean;

    /**
     * 证书持有人信息，非关键参数，固定即可
     * CN=littleutry, OU=utry, O=hy, L=HZ, ST=ZJ, C=CN
     */
    private final static X500Principal DEFAULT_HOLDER_AND_ISSUER
            = new X500Principal("CN=littleutry, OU=utry, O=hy, L=HZ, ST=ZJ, C=CN");

    /**
     * 创建证书生成参数,这里配置的是私钥信息
     *
     * @return 证书生成参数
     */
    private LicenseParam createLicenseParams(){

        Class<LicenseCreator>  clazz = LicenseCreator.class;
        Preferences preferences = Preferences.userNodeForPackage(clazz);
        // 私钥密码
        CipherParam cipherParam = new DefaultCipherParam(licenseConfigBean.getKeyPwd());
        // 密钥库信息加载
        KeyStoreParam keyStoreParam
                = new DefaultKeyStoreParam(
                clazz                                       // 用于获取加载密钥库文件的类加载器，以加载密钥库文件
                , licenseConfigBean.getPrivateStorePath()   // 密钥库文件路径，privateKey.store
                ,licenseConfigBean.getPrivateAlias()        // 密钥别名       privateKey
                , licenseConfigBean.getStorePwd()           // 密钥库密码,这里应该保证和公钥库密码系统
                , licenseConfigBean.getKeyPwd());           // 密钥密码

        LicenseParam licenseParam =
                new DefaultLicenseParam(licenseConfigBean.getSubject(),preferences,keyStoreParam,cipherParam);

        return licenseParam;

    }

    /**
     * 封装证书内容
     *
     * @param extraContent
     * @return
     */
    private LicenseContent createLicenseContent(Date expireTime, Object extraContent){

        LicenseContent content = new LicenseContent();
        Date currentTime = new Date();
        content.setSubject(licenseConfigBean.getSubject());
        content.setConsumerAmount(licenseConfigBean.getConsumerAmount());
        content.setConsumerType(licenseConfigBean.getConsumerType());
        content.setHolder(DEFAULT_HOLDER_AND_ISSUER);
        content.setInfo(licenseConfigBean.getInfo());
        content.setIssued(currentTime);
        content.setIssuer(DEFAULT_HOLDER_AND_ISSUER);
        content.setNotBefore(currentTime);
        content.setNotAfter(expireTime);
        // 扩展参数中放置扩展校验参数
        extraContent = extraContent == null ? new Object(): extraContent;
        content.setExtra(extraContent);
        return content;

    }

    /**
     * 创建证书，以字节数组形式返回
     *
     * @param dto 证书生成参数
     * @return
     */
    public byte[] createLicense(LicenseCreateDTO dto){

        LicenseParam licenseParam = createLicenseParams();
        UtryLicenseManager licenseManager = LicenseManagerHolder.getUtryLicenseManager(licenseParam);
        LicenseContent licenseContent = createLicenseContent(dto.getExpireTime(),dto.convert2ExtraLicenseContent());

        try {
            // 返回证书字节
            return licenseManager.getLicenseBytes(licenseContent);
        }catch (Exception e){
            log.error("生成证书失败！e:{}",e);
            throw ErrorUtil.buildBaseException(ErrorEnum.LICENSE_CREATE_ERROR);
        }

    }

}
